home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 24 / Amiga Format AFCD24 (Feb 1998, Issue 108).iso / -in_the_mag- / emulation / amiga / uae-0.7.0b2 / src / od-pos / pos-disk.c < prev    next >
C/C++ Source or Header  |  1998-01-20  |  12KB  |  450 lines

  1.  /* 
  2.   * UAE - The Un*x Amiga Emulator
  3.   * 
  4.   * pos-disk.c: Creates pseudo dev: handler. Copy tracks to rawfile
  5.   * (used in zfile.c).
  6.   * 
  7.   * Copyright 1997, Samuel Devulder.
  8.   */
  9.  
  10. /****************************************************************************/
  11.  
  12. #include "sysconfig.h"
  13. #include "sysdeps.h"
  14.  
  15. #include <ctype.h>
  16. #include <signal.h>
  17.  
  18. #include "config.h"
  19. #include "options.h"
  20. #include "memory.h"
  21. #include "custom.h"
  22. #include "keyboard.h"
  23. #include "keybuf.h"
  24. #include "disk.h"
  25. #include "debug.h"
  26. #include "gui.h"
  27.  
  28. /****************************************************************************/
  29.  
  30. struct pOS_Locale;
  31. struct pOS_Library;
  32. struct pOS_ExecBase;
  33. struct pOS_DosBase;
  34. struct pOS_Method;
  35. struct pOS_Resource;
  36. struct pOS_RawDoFmtData;
  37. struct pOS_AsciiDoFmtData;
  38. struct pOS_AsciiFmtData;
  39. struct pOS_ClassGrp;
  40. struct pOS_DosDevPathInfo;
  41. struct pOS_ShellScript;
  42. struct pOS_SegmentInfo;
  43. struct IClass;
  44. struct Isrvstr;
  45. struct TagItem;
  46. struct MemHeader;
  47. struct SemaphoreMessage;
  48. struct StackSwapStruct;
  49. struct Interrupt;
  50. struct StandardPacket;
  51. struct InfoData;
  52. struct WBStartup;
  53.  
  54. #define _SIZE_T /* to avoid interference with <sys/types.h> */
  55. #include <pExec/Types.h>
  56. #include <pExec/MsgPort.h>
  57. #include <pExec/Device.h>
  58. #include <pDOS/Lock.h>
  59. #include <pDOS/Files.h>
  60. #include <pDOS/DosSig.h>
  61. #include <pDOS/DosErrors.h>
  62. #include <pDevice/Trackdisk.h>
  63.  
  64. #include <pInline/pExec2.h>
  65. #include <pInline/pDos2.h>
  66.  
  67. extern struct pOS_ExecBase        *gb_ExecBase;
  68. extern struct pOS_ExecLibFunction *gb_ExecLib;
  69. extern struct pOS_DosBase         *gb_DosBase;
  70.  
  71. /****************************************************************************/
  72.  
  73. char *amiga_dev_path  = "DEV:";
  74. char *ixemul_dev_path = "/dev/";
  75.  
  76. int readdevice(char *name, char *dst);
  77. void initpseudodevices(void);
  78. void closepseudodevices(void);
  79. char *to_unix_path(char *s);
  80. char *from_unix_path(char *s);
  81. void split_dir_file(char *src, char **dir, char **file);
  82.  
  83. /****************************************************************************/
  84.  
  85. static char *pseudo_dev_path = "T:DEV";
  86.  
  87. static char pseudo_dev_created  = 0;
  88. static char pseudo_dev_assigned = 0;
  89. static char dfx_done[4];
  90.  
  91. static int device_exists(char *device_name, int device_unit);
  92.  
  93. /****************************************************************************/
  94. /* support routines to handle unix filename convention 
  95.  */
  96. char *to_unix_path(char *s)
  97. {
  98.     char *t,*r,*u;
  99.     int l;
  100.  
  101.     for(u=s,l=0;*u;++u,++l) if(*u=='/' || *u==':') l+=2;
  102.  
  103.     r = t = malloc(1+l);
  104.     if(!r) return NULL;
  105.  
  106.     for(u=s;*u && *u!=':';++u);
  107.     if(*u) {
  108.         *t++='/';
  109.         while(*s!=':') *t++=*s++;
  110.         *t++='/';++s;
  111.     }
  112.     while(*s=='/') {*t++='.';*t++='.';*t++=*s++;}
  113.     while(*s) {
  114.         if(s[0]=='/' && s[1]=='/') {*t++=*s++;*t++='.';*t++='.';*t++=*s++;}
  115.         else *t++=*s++;
  116.     }
  117.     *t='\0';
  118.     return r;
  119. }
  120.  
  121. /****************************************************************************/
  122.  
  123. char *from_unix_path(char *s)
  124. {
  125.     char *t,*r;
  126.  
  127.     r = t = malloc(strlen(s)+1);
  128.     if(!r) return NULL;
  129.  
  130.     if(*s=='/') {
  131.         ++s;
  132.         while(*s && *s!='/') *t++=*s++;
  133.         if(*s=='/') {*t++=':';++s;}
  134.     }
  135.  
  136.     while(*s) {
  137.         if(s[0]=='.' && s[1]=='.') s+=2;
  138.         else *t++=*s++;
  139.     }
  140.  
  141.     *t='\0';
  142.  
  143.     return r;
  144. }
  145.  
  146. /****************************************************************************/
  147.  
  148. void split_dir_file(char *src, char **dir, char **file)
  149. {   /* note: src is freed() */
  150.     char *s=src;
  151.  
  152.     while(*s) ++s;
  153.     while(s>src && (*s!=':' && *s!='/')) --s;
  154.     if(*s==':' || *s=='/') {
  155.         *file = my_strdup(s+1);
  156.         s[1]  = '\0';
  157.         *dir  = my_strdup(src);
  158.         free(src);
  159.     } else {
  160.         *file = src;
  161.         *dir  = my_strdup("");
  162.     }
  163. }
  164.  
  165. /****************************************************************************/
  166. /*
  167.  * Creates peudo DEV:DFx files.
  168.  */
  169. void initpseudodevices(void)
  170. {
  171.     struct pOS_FileLock *lock;
  172.     int i;
  173.  
  174.     /* check for T: and TMP: */
  175.     lock = pOS_LockObject(NULL, "T:", FILELKACC_Shared|FILELKACC_NoReq);
  176.     if(!lock) {
  177.     pOS_CreateDosAssign("T",NULL,"RAM:",DDTYP_Assign);
  178.     } else pOS_UnlockObject(lock);
  179.  
  180.     lock = pOS_LockObject(NULL, "TMP:", FILELKACC_Shared|FILELKACC_NoReq);
  181.     if(!lock) {
  182.     pOS_CreateDosAssign("TMP",NULL,"RAM:",DDTYP_Assign);
  183.     } else pOS_UnlockObject(lock);
  184.  
  185.     pseudo_dev_created  = 0;
  186.     pseudo_dev_assigned = 0;
  187.     for(i=0;i<4;++i) dfx_done[i]=0;
  188.  
  189.     /* check if dev: already exists */
  190.     lock = pOS_LockObject(NULL, amiga_dev_path, 
  191.               FILELKACC_Shared|FILELKACC_NoReq);
  192.     if(!lock) {
  193.         char name[80];
  194.     lock = pOS_LockObject(NULL, pseudo_dev_path, 
  195.                   FILELKACC_Shared|FILELKACC_NoReq);
  196.         if(!lock) {
  197.             /* create it */
  198.             lock = pOS_CreateDirectory(NULL, pseudo_dev_path);
  199.             if(!lock) goto fail;
  200.             pOS_UnlockObject(lock);
  201.         lock = pOS_LockObject(NULL, pseudo_dev_path, 
  202.                   FILELKACC_Shared|FILELKACC_NoReq);
  203.             pseudo_dev_created = 1;
  204.         }
  205.         strcpy(name,amiga_dev_path);
  206.         if(*name && name[strlen(name)-1]==':') name[strlen(name)-1]='\0';
  207.         if(!pOS_CreateDosAssign(name,lock,NULL, DDTYP_Assign)) {
  208.         pOS_UnlockObject(lock);
  209.         goto fail;
  210.     }
  211.         /* the lock is the assign now */
  212.         pseudo_dev_assigned = 1;
  213.     } else pOS_UnlockObject(lock);
  214.  
  215.     /* Create the dev:DFi entry */
  216.     for(i=0;i<4;++i) if(device_exists("pTrackdisk.device",i)) {
  217.         struct pOS_FileHandle *fd;
  218.         char name[80];
  219.  
  220.         sprintf(name,"%sDF%d",amiga_dev_path,i);
  221.         fd = pOS_OpenFile(NULL,name,FILEHDMOD_Write);
  222.         if(fd) {pOS_CloseFile(fd);dfx_done[i]=1;}
  223.     }
  224.  
  225.     return;
  226.  fail:
  227.     fprintf(stderr,"Failed to create pseudo DEV: entry!\n");
  228. }
  229.  
  230. /****************************************************************************/
  231. /*
  232.  * Cleanup pseudo DEV:DFx
  233.  */
  234. void closepseudodevices(void)
  235. {
  236.     int i;
  237.     for(i=0;i<4;++i) if(dfx_done[i]) {
  238.         char name[80];
  239.         sprintf(name,"%sDF%d",amiga_dev_path,i);
  240.         pOS_DeleteObjectName(NULL, name);
  241.         dfx_done[i] = 0;
  242.     }
  243.  
  244.     if(pseudo_dev_assigned) {
  245.         char name[80];
  246.         strcpy(name,amiga_dev_path);
  247.         if(*name && name[strlen(name)-1]==':') name[strlen(name)-1]='\0';
  248.         pOS_DeleteDosAssign(name,NULL,0);
  249.         pseudo_dev_assigned = 0;
  250.     }
  251.  
  252.     if(pseudo_dev_created) {
  253.         pOS_DeleteObjectName(NULL, pseudo_dev_path);
  254.         pseudo_dev_created = 0;
  255.     }
  256. }
  257.  
  258. /****************************************************************************/
  259. /*
  260.  * checks if a device exists
  261.  */
  262. static int device_exists(char *device_name, int device_unit)
  263. {
  264.     struct pOS_MsgPort port;
  265.     struct pOS_TrackdiskIO *IO;
  266.     int ret = 0;
  267.  
  268.     if(pOS_ConstructMsgPort(&port)) {
  269.     IO=(void *)pOS_CreateIORequest(&port, sizeof(struct pOS_TrackdiskIO));
  270.     if(IO) {
  271.         if(!pOS_OpenDevice(device_name, device_unit, 
  272.                    (struct pOS_IORequest*)IO, 0, 0)) {
  273.         pOS_CloseDevice((struct pOS_IORequest*)IO);
  274.         ret = 1;
  275.         }
  276.         pOS_DeleteIORequest((struct pOS_IORequest*)IO);
  277.     }
  278.     pOS_DestructMsgPort(&port);
  279.     }
  280.     return ret;
  281. }
  282.  
  283. /****************************************************************************/
  284. /*
  285.  * extract the device and unit form a filename.
  286.  */
  287. static void extract_dev_unit(char *name, char **dev_name, int *dev_unit)
  288. {
  289.     struct pOS_DosMountDevice *dev = NULL;
  290.     char *s;
  291.  
  292.     if((s = malloc(strlen(name)+2))) {
  293.     sprintf(s,"%s:",name);
  294.     dev = pOS_GetDosMountName(s);
  295.     free(s);
  296.     } 
  297.     if(dev && dev->dmd_Type == DMDTYP_BOD) {
  298.     *dev_name = strdup(dev->dmd_U.dmd_BOD.dmbod_DevName);
  299.     *dev_unit = dev->dmd_U.dmd_BOD.dmbod_UnitNum;
  300.     } else if((s = strrchr(name,'/'))) { 
  301.         /* pTrackdisk[.device]/0 */
  302.         *dev_unit = atoi(s+1);
  303.         *dev_name = malloc(1 + s-name);
  304.         if(*dev_name) {
  305.             strncpy(*dev_name, name, 1 + s-name);
  306.             (*dev_name)[s-name]='\0';
  307.         }
  308.     } else { 
  309.         /* ?? STRANGEDISK0: ?? */
  310.         *dev_unit = 0;
  311.         *dev_name = strdup(name);
  312.     }
  313.     if(*dev_name) {
  314.         char *s;
  315.         if(!(s = strrchr(*dev_name,'.'))) { 
  316.             /* .device is missing: add it */
  317.             s = malloc(8+strlen(*dev_name));
  318.             if(s) {
  319.                 sprintf(s,"%s.device",*dev_name);
  320.                 free(*dev_name);
  321.                 *dev_name = s;
  322.             }
  323.         }
  324.     }
  325. }
  326.  
  327. /****************************************************************************/
  328.  
  329. static int dev_inhibit(char *name, int on)
  330. {
  331.     struct pOS_DosDevice *dev;
  332.     if((dev = pOS_GetDosDevice(NULL, name))) {
  333.     pOS_InhibitDosDevice(dev,on?TRUE:FALSE);
  334.     return 1;
  335.     }
  336.     return 0;
  337. }
  338.  
  339. /****************************************************************************/
  340. /*
  341.  * copy a device to a FILE
  342.  */
  343. static int raw_copy(char *dev_name, int dev_unit, FILE *dst)
  344. {
  345.     struct pOS_MsgPort Port;
  346.     struct pOS_TrackdiskIO *IO;
  347.     int ret = 0;
  348.  
  349.     if(pOS_ConstructMsgPort(&Port)) {
  350.     if((IO=(void*)pOS_CreateIORequest(&Port,sizeof(struct pOS_TrackdiskIO)))) {
  351.     if(!pOS_OpenDevice(dev_name, dev_unit,(struct pOS_IORequest*)IO,0,0)) {
  352.     struct pOS_DriveGeometry Geom;
  353.     char *buf;
  354.  
  355.     memset(&Geom,0,sizeof(struct pOS_DriveGeometry));
  356.     IO->tdio_Command = TDCMD_GetGeometry;
  357.     IO->tdio_Data    = &Geom;
  358.     IO->tdio_Length  = sizeof(struct pOS_DriveGeometry);
  359.     pOS_DoIO((struct pOS_IORequest*)IO);
  360.     if(IO->tdio_Error!=0) {
  361.         Geom.dg_SectorSize   = 512;        
  362.         Geom.dg_TotalSectors = 880*2;
  363.     }
  364.  
  365.     if((buf=pOS_AllocMem(Geom.dg_SectorSize,Geom.dg_BufMemType))) {
  366.         ULONG sec;
  367.         ret = 1;
  368.  
  369.         for(sec = 0; sec<Geom.dg_TotalSectors; ++sec) {
  370.         if((sec % Geom.dg_CylSectors) == 0) {
  371.             printf("Reading sector %d/%d (%02d%%) of %s unit %d    \r",
  372.                sec, Geom.dg_TotalSectors, 
  373.                (100*sec)/Geom.dg_TotalSectors, dev_name, dev_unit);
  374.             fflush(stdout);
  375.         }
  376.         
  377.         IO->tdio_Command = CMD_READ;
  378.         IO->tdio_Data    = buf;
  379.         IO->tdio_Length  = Geom.dg_SectorSize;
  380.         IO->tdio_LOffset = Geom.dg_SectorSize*sec;
  381.         pOS_DoIO((struct pOS_IORequest*)IO);
  382.         if(IO->tdio_Error) printf("Err. on\n");
  383.         if(fwrite(buf,1,Geom.dg_SectorSize,dst)!=Geom.dg_SectorSize) {
  384.             ret = 0; 
  385.             break;
  386.         }
  387.         }
  388.         IO->tdio_Command = TDCMD_Motor;
  389.         IO->tdio_Length  = 0;
  390.         pOS_DoIO((struct pOS_IORequest*)IO);
  391.         printf("                                                                        \r");
  392.         fflush(stdout);
  393.         
  394.         pOS_FreeMem(buf,Geom.dg_SectorSize);
  395.     }
  396.     pOS_CloseDevice((struct pOS_IORequest*)IO);
  397.     }   pOS_DeleteIORequest((struct pOS_IORequest*)IO);
  398.     }   pOS_DestructMsgPort(&Port);
  399.     }
  400.     return ret;
  401. }
  402.  
  403. /****************************************************************************/
  404. /*
  405.  * Copy one raw disk to a file.
  406.  */
  407. int readdevice(char *name, char *dst) 
  408. {
  409.     FILE *f = NULL;
  410.     char *device_name;
  411.     int   device_unit;
  412.     int   retstatus = 0;
  413. #ifdef HAVE_SIGACTION
  414.     struct sigaction oldsa;
  415.     int oldsa_valid;
  416. #endif
  417.     int inhibited;
  418.  
  419. #ifdef HAVE_SIGACTION
  420.     /* disable break */
  421.     oldsa_valid = (0==sigaction(SIGINT, NULL, &oldsa));
  422.     signal(SIGINT, SIG_IGN); /* <--- gcc complains about something */
  423.                              /* in there but I don't know why. */
  424. #endif
  425.     /* get device name & unit */
  426.     extract_dev_unit(name, &device_name, &device_unit);
  427.  
  428.     if(device_name) {
  429.         /* if no destination then just check if the device exists */
  430.         if(dst == NULL) 
  431.            retstatus = device_exists(device_name, device_unit);
  432.         else {
  433.         inhibited = dev_inhibit(name,1);
  434.             /* open dest file */
  435.             if((f = fopen(dst,"wb"))) {
  436.                 retstatus = raw_copy(device_name, device_unit, f);
  437.                 fclose(f);
  438.             }
  439.         if(inhibited) dev_inhibit(name,0);
  440.         }
  441.         free(device_name);           
  442.     }
  443.  
  444. #ifdef HAVE_SIGACTION
  445.     /* enable break */
  446.     if(oldsa_valid) sigaction(SIGINT, &oldsa, NULL);
  447. #endif
  448.     return retstatus;
  449. }
  450.